﻿using System;
using System.Collections.Generic;
using System.Text;
using HL7v_2x;
using System.Diagnostics;
using CLoggerNamespace;

namespace HL7v_2x
{
    

    
    public class HL7
    {
        public HL7SegmentMSH MSH;
        private System.Collections.Generic.List<IHL7Segment> Segments;

        public HL7()
        {
            Debug.WriteLine("[ctor:HL7]: Building... ");
        
            MSH = new HL7SegmentMSH();
            Segments = new List<IHL7Segment>();
            Debug.WriteLine("[ctor:HL7]: Built OK!");
        }

      
    }

    public class HL7v_2x 
    {

        public const string strKeyReturn = "<cr>"; //FD

        private HL7 StructureRequest;
        private HL7 StructureResponse;
        byte[] RequestStream;
        byte[] ResponseStream;
        int ResponseStreamLength;

        

        public HL7v_2x()
        {
           /* string strLogDirectory = "C:\\Fabio\\logs\\HL7Server\\";
            string strLogPrefix = "HL7Service";           
                        
            CLogger.Append("DIR: "+strLogDirectory+", FILE: "+strLogPrefix, CLogger.INFO);
            */
            CLogger.Append("\n ***************** INICIALICE HL7 ********************", CLogger.INFO);

            StructureRequest = new HL7();
            StructureResponse = new HL7();

        }

        #region Methods todos

        #region OBTENER LISTA DE SEGMENTOS DIVIDIDOS POR RETURNS <CR>
        public List<string> ObtenerListSegmentosConCR(string strMsgHL7Rx)
        {
            List<string> lststrAux = new List<string>();

           // CLogger.Append("Mensaje Leido:" + strMsgHL7Rx + " (" + strMsgHL7Rx.Length.ToString() + " caracter(es))", CLogger.INFO);

            CLogger.Append("Mensaje Leido:" + strMsgHL7Rx + " (" + strMsgHL7Rx.Length.ToString() + " caracter(es))", CLogger.INFO);
            if (strMsgHL7Rx.Contains(strKeyReturn))
            {

                int inIndice = 0;
                int inLastinCR=0;                
                int inDatosACortar = 0;

                while ((strMsgHL7Rx.Length > inIndice) && (inLastinCR >= 0))
                {
                   // CLogger.Append("INDICE: " + inIndice.ToString(), CLogger.INFO);

                    if((inLastinCR = strMsgHL7Rx.IndexOf(strKeyReturn,inIndice))!=-1)
                    {
                       // CLogger.Append("LENGTH HASTA RETURN: " + inLastinCR.ToString(), CLogger.INFO);                    
                        inDatosACortar = inLastinCR - inIndice;
                       // CLogger.Append("CANT DATOS A CORTAR: " + inDatosACortar.ToString(), CLogger.INFO);
                        CLogger.Append("SEGMENTO A COPIAR: " + strMsgHL7Rx.Substring(inIndice, inDatosACortar), CLogger.INFO);
                        lststrAux.Add(strMsgHL7Rx.Substring(inIndice,  inDatosACortar));
                        inIndice = inLastinCR + 4;
                    }

                }

               /* int inx=0;
                foreach(string strSegmentosenlist in lststrAux)//Leer lista de segmentos
                {
                    CLogger.Append("Segmento "+inx.ToString()+" : " + strSegmentosenlist, CLogger.INFO);
                    inx++;
                }*/
            }
            else
            {
                return null;
            }

            return lststrAux;
        }
        #endregion



        public bool Assemble()
        {
            return false;
        }

        #region DISASSEMBLE
        public bool Disassemble()
        {
           
            bool result = false;
           
            List<string> lstrSegmentosHL7=new List<string>();

            try
            {
                Debug.WriteLine("[Disassemble]: Starting... ");

                string str;
                System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
                str = enc.GetString(RequestStream);

                lstrSegmentosHL7 = ObtenerListSegmentosConCR(str);

                List<HL7Fields> lstHL7Fields = ProcesarSegmentosYObtenerCampos(lstrSegmentosHL7);
                //                            = ProcesarCamposYObtenerSubCampos();

            }
            catch (Exception ex)
            {
                CLogger.Append("Excepcion desensamblando segmentos: " + ex.Message, CLogger.ERROR);
            }

            return result;
        }
        #endregion


     
        public void SetRequestStream(int intBytesReadParam, byte[] byteInputStreamParam)
        {
            

            RequestStream = new byte[intBytesReadParam];
            

            System.Buffer.BlockCopy(byteInputStreamParam, 0, RequestStream, 0, intBytesReadParam);

            string str;
            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            str = enc.GetString(RequestStream);

            CLogger.Append("Set Input RequestStream Rx: " + str + " BYTES READ: " + intBytesReadParam.ToString(), CLogger.INFO);


        }
        public byte[] GetResponseStream()
        {
            return ResponseStream;
        }
        public int GetResponseStreamLength()
        {
            return ResponseStreamLength;
        }
        public byte[] GetRequestStream()
        {
            return RequestStream;
        }
        public int GetRequestStreamLength()
        {
            return RequestStream.Length;
        }
        #endregion

        #region METODOS PARA CADA SEGMENTO

        /*public bool IsMSHInRequest()
        {
            if (RequestStream.Length < 3)
            {
                throw new Exception("La trama de entrada tiene " + RequestStream.Length.ToString()+ " digitos, no se puede verificar el header MSH ");
            }
            Debug.WriteLine("[IsMSHInRequest] Esta MSH => " + (HomeroFormatter.HomeroFormatter.GetString(RequestStream, 3) == "MSH").ToString());
            return (HomeroFormatter.HomeroFormatter.GetString(RequestStream, 3) == "MSH");

        }*/
        
        

        #endregion

        #region METODOS GENERALES

        public List<HL7Fields> ProcesarSegmentosYObtenerCampos(List<string> strListSegmHL7)
        {
             //HL7MessageName objMessageName = new HL7MessageName();   // FD
             //HL7EventType objEventType = new HL7EventType(); //FD
             //HL7MessageType objMessageType = new HL7MessageType(); //FD
            List<HL7Fields> lstHL7Field = new List<HL7Fields>();
            IHL7Segment objHL7Segment;
           // strTipoMensaje=GetTipoMensaje(strListSegmHL7[0]);
            lstHL7Field = null;

            foreach (string strSegment in strListSegmHL7)
            {

                objHL7Segment = GetObjectSegment(strSegment);
                lstHL7Field=objHL7Segment.DesarmarSegmentoEnCampos(strSegment);

            }

           
            return lstHL7Field;
            
        }

        public static string GetFromStartStrHL7(string strHL7toGet,int inLengthtoGet)
        {
            return strHL7toGet.Substring(0, inLengthtoGet); ;
        }

        public IHL7Segment GetObjectSegment(string strSegmento)
        {


            switch (GetFromStartStrHL7(strSegmento, 3))
            {
                case HL7MessageName.MessageACC:
                    return new HL7SegmentACC();
                    
                case HL7MessageName.MessageAL1:
                    return new HL7SegmentAL1();

                case HL7MessageName.MessageALG:
                    return new HL7SegmentALG();

                case HL7MessageName.MessageBLG:
                    return new HL7SegmentBLG();

                case HL7MessageName.MessageCTD:
                    return new HL7SegmentCTD();

                case HL7MessageName.MessageCTI:
                    return new HL7SegmentCTI();
                    
                case HL7MessageName.MessageDB1:
                    return new HL7SegmentDB1();
                    
                case HL7MessageName.MessageDG1:
                    return new HL7SegmentDG1();
                    
                case HL7MessageName.MessageDRG:
                    return new HL7SegmentDRG();
                    
                case HL7MessageName.MessageDSC:
                    return new HL7SegmentDSC();
                    
                case HL7MessageName.MessageERR:
                    return new HL7SegmentERR();
                    
                case HL7MessageName.MessageEVN:
                    return new HL7SegmentEVN();
                    
                case HL7MessageName.MessageGT1:
                    return new HL7SegmentGT1();
                    
                case HL7MessageName.MessageIN1:
                    return new HL7SegmentIN1();
                    
                case HL7MessageName.MessageIN2:
                    return new HL7SegmentIN2();
                    
                case HL7MessageName.MessageIN3:
                    return new HL7SegmentIN3();
                    
                case HL7MessageName.MessageMRG:
                    return new HL7SegmentMRG();

                case HL7MessageName.MessageMSA:
                    return new HL7SegmentMSA();

                case HL7MessageName.MessageMSH:
                    CLogger.Append("MENSAJE MSH DETECTED", CLogger.INFO);
                    return new HL7SegmentMSH();
                    
                case HL7MessageName.MessageNK1:
                    return new HL7SegmentNK1();                    

                case HL7MessageName.MessageNPU:
                    return new HL7SegmentNPU();
                    
                case HL7MessageName.MessageNTE:
                    return new HL7SegmentNTE();
                    
                case HL7MessageName.MessageOBR:
                    return new HL7SegmentOBR();                    

                case HL7MessageName.MessageOBX:
                    return new HL7SegmentOBX();

                case HL7MessageName.MessageODS:
                    return new HL7SegmentODS();
                    
                case HL7MessageName.MessageODT:
                    return new HL7SegmentODT();
                    
                case HL7MessageName.MessageORC:
                    return new HL7SegmentORC();
                    
                case HL7MessageName.MessagePD1:
                    return new HL7SegmentPD1();
                    
                case HL7MessageName.MessagePID:
                    return new HL7SegmentPID();
                    
                case HL7MessageName.MessagePR1:
                    return new HL7SegmentPR1();
                    
                case HL7MessageName.MessagePV1:
                    return new HL7SegmentPV1();
                    
                case HL7MessageName.MessagePV2:
                    return new HL7SegmentPV2();
                    
                case HL7MessageName.MessageROL:
                    return new HL7SegmentROL();
                    
                case HL7MessageName.MessageRQ1:
                    return new HL7SegmentRQ1();
                    
                case HL7MessageName.MessageRQD:
                    return new HL7SegmentRQD();
                    
                case HL7MessageName.MessageRXO:
                    return new HL7SegmentRXO();
                    
                case HL7MessageName.MessageUB1:
                    return new HL7SegmentUB1();
                    
                case HL7MessageName.MessageUB2:
                    return new HL7SegmentUB2();
                    
                case HL7MessageName.MessageZBR:
                    return new HL7SegmentZBR();

                default:
                    throw new NotImplementedException("No existe el mensaje HL7");

            }
        }
        

        #endregion




    }
}
